package node;

import lexer.LexType;
import parser.Parser;

import java.io.IOException;
import java.util.List;

public class ExpNode extends ASTNode {
    // 定义Exp的头符号集
    public static final LexType[] first = { LexType.IDENFR, LexType.PLUS,
            LexType.MINU, LexType.NOT, LexType.LPARENT, LexType.INTCON,
            LexType.CHRCON };
    public final String name = "<Exp>";
    // Exp → AddExp
    private final AddExpNode addExpNode;

    public ExpNode(AddExpNode addExpNode) {
        this.addExpNode = addExpNode;
    }

    public static boolean contains(LexType lexType) {
        for (LexType type : first) {
            if (type == lexType) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void show() throws IOException {
        addExpNode.show();
        Parser.parserWriter.write(name + "\n");
    }

    public AddExpNode getAddExpNode() {
        return addExpNode;
    }

    public int calculate() {
        // 确定当前Exp是加减乘除计算，即一定可以被计算出具体的数值
        // 输入：AddExpNode addExpNode
        // 输出：一个int类型的数字
        return addExpNode.calculate();
    }

    // 获取Exp的Ident,只有Ident可能为数组时，才返回Ident，否则返回null
    public String getIdent() {
        // Exp → AddExp
        // AddExp → MulExp { ('+' | '-') MulExp}
        // MulExp → UnaryExp { ('*' | '/') UnaryExp}
        // UnaryExp → PrimaryExp | Ident '(' [FuncRParams] ')' | UnaryOp UnaryExp
        // PrimaryExp → '(' Exp ')' | LVal | Number | Character
        // LVal → Ident ['[' Exp ']']
        // 当且仅当，Exp为Ident时，返回Ident，否则返回null
        if (this.getAddExpNode() == null) {
            return null;
        }

        List<MulExpNode> mulExpNodes = this.getAddExpNode().getMulExpNodeList();
        if (mulExpNodes == null || mulExpNodes.isEmpty()) {
            return null;
        }

        MulExpNode firstMulExpNode = mulExpNodes.get(0);
        List<UnaryExpNode> unaryExpNodes = firstMulExpNode.getUnaryExpNodeList();
        if (unaryExpNodes == null || unaryExpNodes.isEmpty()) {
            return null;
        }

        UnaryExpNode firstUnaryExpNode = unaryExpNodes.get(0);
        PrimaryExpNode primaryExpNode = firstUnaryExpNode.getPrimaryExpNode();
        if (primaryExpNode == null || primaryExpNode.getlValNode() == null) {
            return null;
        }

        String identNode = primaryExpNode.getlValNode().getIdentNode();
        boolean isMayArray = primaryExpNode.getlValNode().isMayArray();
        if (identNode != null && isMayArray) {
            return identNode;
        }
        return null;
    }

    public boolean canCaclulate() {
        return addExpNode.canCaclulate();
    }
}
